home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / A86V402.ZIP / A10.DOC < prev    next >
Text File  |  1995-05-22  |  33KB  |  691 lines

  1. CHAPTER 10   RELOCATION AND LINKAGE
  2.  
  3.  
  4. A86 allows you to produce either .COM files, which can be run
  5. immediately as standalone programs, or .OBJ files, to be fed to
  6. the MS-DOS LINK program.  In this chapter I'll discuss .OBJ mode
  7. of A86.
  8.  
  9.  
  10. .OBJ Production Made Easy
  11.  
  12. I'll start by giving you the minimum amount of information you
  13. need to know to produce .OBJ files.  If you are writing short
  14. interface routines, and do not want to concern yourself with the
  15. esoterica of .OBJ files (segments, groups, publics, etc.), you
  16. can survive quite nicely by reading only this section.
  17.  
  18. There are two ways you can cause A86 to produce a .OBJ file as
  19. its object output.  One way is to explicitly give .OBJ as the
  20. output file name: for example, you can assemble the source file
  21. FOO.8 by giving the command "A86 FOO.8 FOO.OBJ".  The other way
  22. is to specify the switch +O (letter O not digit 0).  This is
  23. illustrated by the invocation "A86 +O FOO.8", which will have the
  24. same effect as the first invocation.
  25.  
  26. My design philosophy for .OBJ production is to accommodate two
  27. types of user.  The first type of user is writing new code, to
  28. link to other (usually high level language) modules.  That person
  29. should be able to write the module with a minimum of red tape,
  30. and have A86 do the right thing.  The second type of user has
  31. existing modules written for Intel/IBM assemblers, and wants to
  32. port them to A86.  A86 should recognize and act upon all the
  33. relocation directives (SEGMENT, GROUP, PUBLIC, EXTRN, NAME, END)
  34. given.  The assembly should work even if several files, assembled
  35. separately under the Intel/IBM assembler, are fed to a single A86
  36. assembly.  You'll see if you read on through this entire chapter
  37. that the multiple-files requirement causes A86 to interpret some
  38. of the relocation directives a little differently (while
  39. achieving compatible results).
  40.  
  41. Let's suppose you're writing new code: for example, an interface
  42. routine to the "C" language, that multiplies a 16-bit number by
  43. 10.  "C" pushes the input number onto the stack, before calling
  44. your routine.  Your code needs to get the number, multiply it by
  45. 10, and return the answer in the AX register.  You can code it:
  46.  
  47. _MUL10:          ; "C" expects all public names to start with "_"
  48.   PUSH BP        ; "C" expects BP to be preserved
  49.   MOV BP,SP      ; we use BP to address the stack
  50.   MOV AX,[BP+4]  ; fetch the number N, beyond BP and the ret addr
  51.   ADD AX,AX      ; 2N
  52.   MOV BX,AX      ; 2N is saved in BX
  53.   ADD AX,AX      ; 4N
  54.   ADD AX,AX      ; 8N
  55.   ADD AX,BX      ; 8N + 2N = 10N
  56.   POP BP         ; BP is restored
  57.   RET            ; go back to caller
  58.                                                              10-2
  59.  
  60. These 11 lines can be your entire source file!  If you name the
  61. file MUL10.8, A86 will create an object file MUL10.OBJ, that
  62. conforms to the standard SMALL model of computation for high
  63. level languages.  If you use RETF instead of RET (thus, by the
  64. way, getting the operand from BP+6 instead of BP+4), the object
  65. module will conform to the standard LARGE model of computation.
  66. All the red tape information required by the high level language
  67. is provided implicitly by A86.  I'll go through this information
  68. in detail later, but you should need to read about it only if
  69. you're curious.
  70.  
  71. What happens if you need to access symbols outside the module
  72. you're assembling?  If the type of the symbol is correctly
  73. guessed from the instruction that refers to it, then you can
  74. simply refer to it, and leave it undefined within the module. For
  75. example, if A86 sees the instruction CALL PRINT with PRINT
  76. undefined, it will assume that PRINT is a NEAR procedure.  If
  77. PRINT is never defined within the module, A86 will act as if you
  78. declared PRINT via the directive EXTRN PRINT:NEAR.  The address
  79. of PRINT will be plugged into your instruction by LINK when it
  80. combines A86's .OBJ file with the high level language's .OBJ
  81. files, to make the final program.
  82.  
  83. In general, the undefined operand to any CALL or JMP instruction
  84. is assumed to be NEAR.  The second (source) operand to a MOV or
  85. arithmetic instruction is assumed to be ABS (i.e., an immediate
  86. constant).  An undefined first (destination) operand is assumed
  87. to be a simple memory variable, of the same size (BYTE or WORD)
  88. as the register given in the second operand.  If your external
  89. symbol does not comply with these guidelines, you need to declare
  90. it with an EXTRN before you use it.  (You can also use EXTRN to
  91. declare types of non-complying forward references within your
  92. module, as you'll see later.)
  93.  
  94. If you'd like to link the MUL10 procedure to Turbo Pascal V4.0 or
  95. later, you need to append the line CODE SEGMENT PUBLIC to the top
  96. of the program, to name the program segment according to Turbo
  97. Pascal's expectations.  You may dispense with the leading
  98. underscore in the name MUL10-- Turbo Pascal does not require or
  99. expect it.
  100.  
  101. At this point, if you're a casual user, I think you've read
  102. enough to get going!  Read further only if you wish; or if you
  103. get stuck, and need to master the esoterica.
  104.                                                              10-3
  105.  
  106. Overview of Relocation and Linkage
  107.  
  108. When you assemble a program directly into a .COM file, the
  109. program has just two forms: the source program, that you can
  110. understand, and the .COM file, that the computer can "understand"
  111. (i.e., execute).  A .OBJ file is an intermediate format: neither
  112. you nor the (executing) computer can make sense out of a .OBJ
  113. file; only programs like LINK interpret .OBJ files.  The purpose
  114. of a .OBJ file is to allow you to assemble or compile just a part
  115. of a program.  The other parts (also in the form of .OBJ files)
  116. can be produced at a different time; often by a different
  117. assembler or compiler, whose source files are in a different
  118. language.  It's easy to see where the word "linkage" comes from:
  119. the LINK program puts the pieces of a program together.  The
  120. "relocation" comes because the assembler or compiler that makes a
  121. given program piece doesn't know how many other pieces will come
  122. before it, or how big the other pieces will be.  Each piece is
  123. constructed as if it started at location 0 within the program;
  124. then LINK "relocates" the piece to its true location.
  125.  
  126. Many of the relocation features of 86 assembly language are
  127. couched in terms of LINK's point of view, so we must look at the
  128. way LINK sees things.  LINK calls a .OBJ file an "object module",
  129. or just "module".  Each module has a NAME, that can be referred
  130. to when LINK issues diagnostic messages, such as error messages
  131. and symbol maps.  If a program symbol is used only within a
  132. single module, it does not need to be given to LINK, except
  133. possibly to pass along to a symbolic debugger.  On the other
  134. hand, if a program symbol is defined in one module and referenced
  135. in other modules, then LINK needs to know the name of the symbol,
  136. so it can resolve the references.  Such a symbol is PUBLIC in the
  137. module in which it is defined; it is "external" in the other
  138. modules, containing references to it.  Finally, exactly one
  139. module in a program must contain the starting location for the
  140. program; that module is called the "main module", and it must
  141. supply the starting address (which is not necessarily at the
  142. beginning of the module).
  143.  
  144. In the 86 family of microprocessors, the LINK system also does
  145. much to manage the memory segments that a program will fit into,
  146. and get its data from.  The (grotesquely ornate) level of support
  147. for segmentation was dictated by Intel, when it specified (and
  148. IBM and the compiler makers accepted) the format that .OBJ files
  149. will have.  I attended the fateful meeting at Intel, in which the
  150. crucial design decisions were made.  I regret to say that I sat
  151. quietly, while engineers more senior than I applied their fertile
  152. imaginations to construct fanciful scenarios which they felt had
  153. to be supported by LINK.  Let's now review the resulting
  154. segmentation model.
  155.                                                              10-4
  156.  
  157. The parts of a program, as viewed by LINK, come in three
  158. different sizes: they can be (1) pieces of a single segment, (2)
  159. an entire single segment, or (3) a sequence of consecutive
  160. segments in 86 memory.  Size (1) should have been called
  161. something like FRAGMENT, but is instead called SEGMENT.  Size (2)
  162. should have been called SEGMENT, but is instead called GROUP.
  163. Size (3) should have been called "group", but is instead called
  164. "class".  Let me cling to the sensible terminology for one more
  165. paragraph, while I describe the worst scenario Intel wanted to
  166. support; then when I discuss individual directives, I'll
  167. regretfully revert to the official terminology.
  168.  
  169. The scenario is as follows: suppose you have a program that
  170. occupies about 100K bytes of memory.  The program contains a core
  171. of 20K bytes of utility routines that every part of the program
  172. calls.  You'd like every part of the program to be able to call
  173. these routines, using the NEAR form to save memory.  By gum, you
  174. can do it!  You simply(!) slice the program into three fragments:
  175. the utility routines will go into fragment U, and the rest of the
  176. program will be split into equal-sized 40K-byte fragments A and
  177. B.  Now you arrange the fragments in 8086 memory in the order
  178. A,U,B.  The fragments A and U form a 60K-byte block, addressed by
  179. a segment register value G1, that points to the beginning of A.
  180. The fragments U and B form another 60K-byte block addressed by a
  181. segment register value G2, that points to the beginning of U.  If
  182. you set the CS register to G1 when A is executing, and G2 when B
  183. is executing, the U fragment is accessible at all times.  Since
  184. all direct JMPs and CALLs are encoded as relative offsets, the
  185. U-code will execute direct jumps correctly whether addressed by
  186. G1 with a huge offset, or G2 with a small offset.  Of course, if
  187. U contains any absolute pointers referring to itself (such as an
  188. indirect near JMP or CALL), you're in trouble.
  189.  
  190. It's now been over a decade since the fateful design meeting took
  191. place, and I can report that the above scenario has never taken
  192. place in the real world.  And I can state with some authority
  193. that it never will.  The reason is that the only programs that
  194. exceed 64K bytes in size are coded in high level language, not
  195. assembly language.  High-level-language compilers follow a very,
  196. very restricted segmentation model-- no existing model comes
  197. remotely close to supporting the scheme suggested by the
  198. scenario.  But the 86 assembly language can support it-- the
  199. directives "G1 GROUP A,U" and "G2 GROUP B,U", followed by chunks
  200. of code of the appropriate object size, headed by directives "A
  201. SEGMENT", "B SEGMENT", and "U SEGMENT".  The LINK program is
  202. supposed to sort things out according to the scenario; but I
  203. can't say (and I have my doubts) if it actually succeeds in doing
  204. so.
  205.  
  206. The concept of "class" was added as an afterthought, to implement
  207. the more sensible and usable features that outsiders thought
  208. GROUPs were implementing;  namely, the ability to specify that
  209. different (and disjoint!) segments occur consecutively in memory.
  210. This allows programs to be arranged in a consistent manner-- for
  211. example, with all program code followed by all static data
  212. segments followed by all dynamically allocated memory.
  213.                                                              10-5
  214.  
  215. The NAME Directive
  216.  
  217. Syntax:  NAME module_name
  218.  
  219. The NAME directive specifies that "module_name" be given to LINK
  220. as the name of the module produced by this assembly.  The symbol
  221. "module_name" can be used elsewhere in your program without
  222. conflict: it can even, if you like, be a built-in assembler
  223. mnemonic (e.g. "NAME MOV" is acceptable)!
  224.  
  225. If you do not provide a NAME directive, A86 will use the name of
  226. the output object file, without the .OBJ extension.   If you
  227. provide more than one NAME directive, A86 will use the last one
  228. given, with no error reported.
  229.  
  230.  
  231.  
  232. The PUBLIC Directive
  233.  
  234. Syntax:  PUBLIC  sym1, sym2, sym3, ...
  235.          PUBLIC
  236.  
  237. The PUBLIC directive allows you to explicitly list the symbols
  238. defined in this assembly, that can be used by other modules.  If
  239. you do not give any PUBLIC directives in your program, A86 will
  240. use every relocatable label and variable name in your program,
  241. except local labels (the redefinable labels consisting of a
  242. letter followed by digits: L7, M1, Q234, etc.).  Symbols EQUated
  243. to constants, and symbols defined within structures and DATA
  244. SEGMENTs, are not implicitly declared PUBLIC: you have to
  245. explicitly include them in a PUBLIC directive.
  246.  
  247. A86 maintains an internal flag, telling it whether to figure out
  248. for itself which symbols are PUBLIC, or to let the program
  249. explicitly declare them.  The flag starts out "implicit", and is
  250. set to "explicit" only if A86 sees a PUBLIC directive with no
  251. names at all, or a PUBLIC directive containing at least one name
  252. that would have been implicitly made PUBLIC.
  253.  
  254. If you are writing new code, you'll probably want to keep the
  255. flag "implicit".  You use the PUBLIC directive only for those
  256. symbols which have the form of local labels, but aren't (e.g., a
  257. memory variable I1987 for 1987 income); and for absolute values
  258. that are globally accessed -- e.g. specify "PUBLIC
  259. OPEN_FILES_LIMIT" for a symbol defined as "OPEN_FILES_LIMIT EQU
  260. 20".
  261.  
  262. If you are porting existing code, that code will already have
  263. PUBLIC directives in it, and A86 will go to "explicit" mode,
  264. duplicating the functionality of other assemblers.
  265.  
  266. The PUBLIC directive with no names is used to force "explicit"
  267. mode, thus causing (if there are no further PUBLICs with names)
  268. the .OBJ file to declare no symbols PUBLIC.
  269.                                                              10-6
  270.  
  271. There is another side effect to the PUBLIC directive: if a symbol
  272. is declared PUBLIC in a module, it had better be defined in that
  273. module.  If it isn't then A86 includes it in the .UND listing of
  274. undefined symbols in the module, and suppresses output of the
  275. object file.
  276.  
  277.  
  278. The EXTRN Directive
  279.  
  280. Syntax:  EXTRN  sym1:type, sym2:type, ...
  281.  
  282. where "type" is one of:  BYTE WORD DWORD QWORD TBYTE FAR
  283. or synonymously:           B    W    D     Q     T     F
  284. or:                        NEAR  ABS  PROC
  285.  
  286. The EXTRN directive allows you to attach a type to a symbol that
  287. may not yet be defined (and may never be defined) within your
  288. program.  This is often necessary for the assembler to generate
  289. the correct instruction form when the symbol is used as an
  290. operand.  All the possible types except ABS and PROC are defined
  291. elsewhere in the A86 language, but I list them again here for
  292. convenience:
  293.  
  294.    B or BYTE:   byte-sized memory variable
  295.    W or WORD:   word (2 byte) sized memory variable
  296.    D or DWORD:  doubleword (4-byte) sized memory variable
  297.    Q or QWORD:  quadword (8-byte) sized memory variable
  298.    T or TWORD:  10-byte-sized memory variable
  299.    NEAR:        program label accessed within a segment
  300.    FAR:         program label accessed from outside this segment
  301.    ABS:         an absolute number (i.e., an immediate constant)
  302.    PROC:        same as NEAR unless you provide a PROC EQU FAR
  303.  
  304. An example of EXTRN usage is as follows: suppose there is a word
  305. memory variable IFARK in your program.  The variable might be
  306. declared at the end of the program; or it might be defined in a
  307. module completely outside of this program.  Without an EXTRN
  308. directive, A86 will assemble an instruction such as "MOV
  309. AX,IFARK" as the loading of an immediate constant IFARK into the
  310. AX register.  If you place the directive "EXTRN IFARK:W" at the
  311. top of your program, you'll get the correct instruction form for
  312. MOV AX,IFARK-- moving a word-memory variable into the AX
  313. register.
  314.  
  315. A86 will allow more than one EXTRN directive for a given symbol,
  316. as long as the same type is given every time.  A86 will even
  317. allow an EXTRN directive for a symbol that has already been
  318. defined, as long as the type declared is consistent with the
  319. symbol's definition.  These allowances exist so that you can
  320. assemble multiple files written for another assembler, that had
  321. been fed separately to that assembler.
  322.                                                              10-7
  323.  
  324. Note that EXTRN is viewed quite differently by A86 than by other
  325. assemblers.  In fact, if it weren't for those other assemblers,
  326. I'd use the mnemonic DECLARE instead of EXTRN.  A86 doesn't
  327. really use EXTRN to determine which symbols are external-- it
  328. uses those symbols that are undefined at the end of assembly.  As
  329. I stated earlier in the chapter, an undefined symbol can be
  330. referenced without being declared via EXTRN. Conversely, a
  331. defined symbol can be declared (and redeclared) via EXTRN; being
  332. defined, such a symbol will not be specified "external" in the
  333. .OBJ file.
  334.  
  335. Because EXTRN is useful in forward reference situations, it is
  336. now recognized even when A86 is assembling a .COM file.
  337.  
  338. For those of you who are accustomed to the more traditional use
  339. of EXTRN, and who do not like external records to be created
  340. "behind your back", A86 offers the "+G16" option.  If you include
  341. "+G16" in the program invocation, A86 will require that all
  342. undefined symbols be explicitly declared via an EXTRN.  Any
  343. undefined, undeclared symbols will be included in the .UND
  344. listing of undefined symbols, and object-file output will be
  345. suppressed.
  346.  
  347.  
  348. MAIN: The Starting Location for a Program
  349.  
  350. I've already stated that exactly one module in a program is the
  351. "main" module, containing the starting address of the entire
  352. program.  In A86 when assembling .OBJ files, the starting address
  353. is given by the label MAIN.  You simply provide the label "MAIN:"
  354. where you want the program to start.  The module containing MAIN
  355. is the main module.  Note that if you have the +c
  356. case-sensitivity switch enabled, MAIN must be in all-caps.
  357.  
  358.  
  359. The END Directive
  360.  
  361. Syntax:  END
  362.          END start_addr
  363.  
  364. The END directive is used by other assemblers for two purposes,
  365. both of which are now a little silly.  The first purpose is to
  366. signal the end of assembly.  This was necessary back in the days
  367. when source files were input on media such as paper tape: you had
  368. to tell the assembler explicitly that the content of the tape has
  369. ended.  Today the operating system can tell you when you've
  370. reached the end of the file, so this function is an anachronism.
  371.                                                              10-8
  372.  
  373. The second purpose of END is, nonsensically, to allow you to
  374. specify the starting location of the program.  I suppose the
  375. person who wrote the first assembler back in the 1950's was too
  376. short on memory to implement a separate START directive, or a
  377. MAIN label like A86 has, and decided to let END do double duty.
  378. I've always considered the example "END START" to have an
  379. Alice-in-Wonderland quality; it is fuel for the
  380. high-level-language snobs who like to attack assembly language.
  381. Please defeat the snobs, and use "MAIN:" if you are writing new
  382. code.
  383.  
  384. For compatibility, A86 treats "END start_addr" exactly the same
  385. as if you had coded "MAIN EQU start_addr".  Note that if you want
  386. your program to assemble under both A86 and other assemblers, you
  387. can specify "END MAIN"-- A86 treats MAIN EQU MAIN as a legal
  388. redefinition of the symbol MAIN.
  389.  
  390. A86 ignores END when there is no starting-address operand, thus
  391. allowing assembly of multiple files written for other assemblers.
  392.  
  393.  
  394. The SEGMENT Directive
  395.  
  396. Syntax:  seg_name SEGMENT [align] [combine] [use] ['class_name']
  397.  
  398. where "align" is one of:  BYTE   WORD   PARA   PAGE
  399. "combine"     is one of:  PUBLIC  STACK  COMMON  MEMORY
  400.                             AT number
  401. "use"         is one of:  USE16  USE32  FLAT
  402.  
  403. The SEGMENT directive says that assembled object code will
  404. henceforth go to a block of code whose name is "seg_name".
  405. "seg_name" is a symbol that represents a value that can be loaded
  406. into a segment register.  If "seg_name" is not declared in a
  407. GROUP directive, then its value should in fact be loaded into a
  408. segment register, in order to address the code.  If "seg_name" is
  409. declared in a GROUP directive, then the code is a part of the
  410. segment addressed by the name of the group.
  411.  
  412. A program can consist of any number of named segments, to be
  413. combined in numerous exotic ways to produce the final program.
  414. You can redirect your object output from one segment to another
  415. in your assembly, by providing a SEGMENT directive before each
  416. piece of code.  You can even return to a segment you started
  417. earlier, by repeating a SEGMENT with the same name-- the
  418. assembler just picks up where it left off, subject to some
  419. possible skipping for memory alignment, that I'll describe
  420. shortly.
  421.                                                              10-9
  422.  
  423. The specifications following the word SEGMENT help to describe
  424. how the code in this module's part of the segment will be
  425. combined with code for the same segment name given in other
  426. modules; and also how this named segment will be grouped with
  427. other named segments.  Other assemblers require the
  428. specifications to be given in the order indicated.  A86 will
  429. accept any order, and will accept commas between the
  430. specifications if you want to provide them.  The only restriction
  431. is that "AT number" must be followed by a comma if it is not the
  432. last specification on the line.
  433.  
  434. The "align" specification tells if each piece of code within the
  435. segment should be aligned so that its starting address is an even
  436. multiple of some number.  BYTE alignment means there is no
  437. requirement; WORD alignment requires each piece to start at a
  438. multiple of 2; PARA alignment, at a multiple of 16; PAGE
  439. alignment, at a multiple of 256.  For example, suppose you have a
  440. segment containing memory variables.  You can declare the segment
  441. with the statement "VAR_DATA SEGMENT WORD", which ensures that
  442. the segment is aligned to an even memory address.  That way you
  443. can insure that all 16-bit and bigger memory quantities in the
  444. segment are aligned to even addresses, for faster access on the
  445. 16-bit machines of the 86 family.
  446.  
  447. There are special rules governing alignment for multiple pieces
  448. of the same named segment within the same program module.  Other
  449. assemblers outlaw conflicting alignment specifications in this
  450. situation; A86 accepts them, and uses the strictest specification
  451. given.  Furthermore, the alignment given for any specification
  452. beyond the first will control the alignment for that piece of
  453. code within this module's chunk.  For example, if a program
  454. contains two pieces of code headed by "VAR_DATA SEGMENT WORD",
  455. A86 will insert a byte between the pieces if the first piece has
  456. an odd number of bytes.  This insures correct assembly for
  457. multiple files written for another assembler.
  458.  
  459. If no "align" type is given for any of the pieces of a named
  460. segment, an alignment of PARA is assumed.
  461.  
  462.  
  463. The "combine" specification tells how the chunk of code from this
  464. module will be combined with the chunks of the same named
  465. segment, that come from other modules.  Yes, I know, that sounds
  466. like what "align" does; but "combine" takes a different, more
  467. major point of view:
  468.  
  469. * PUBLIC is the kind of combination we've been talking about all
  470.   along: each piece of the segment is located off the end of the
  471.   previously linked piece, subject to possible gaps for
  472.   alignment.  The size of the segment is the sum of the sizes of
  473.   the pieces, plus the sizes of the gaps.
  474.  
  475. * STACK is a combination type reserved for the system's stack
  476.   segment.  To illustrate how STACK segment chunks are combined,
  477.   let's describe the only way a stack segment should ever be
  478.   used.  We'll call the segment STACK; and we declare it as
  479.   follows:
  480.                                                             10-10
  481.  
  482.     STACK SEGMENT WORD STACK
  483.         DW 100 DUP (?)
  484.     TOP_OF_STACK:
  485.  
  486.   The code just given declares a stack area of 200 bytes (100
  487.   words) for this module.  If identical code occurs in each of
  488.   three modules which are then linked together, the resulting
  489.   STACK segment will have 600 bytes (the sizes are added), but
  490.   TOP_OF_STACK will be the same address (600) for each module
  491.   (each piece is overlayed at the top of the segment).  That way,
  492.   every module can declare and access the top of the stack, which
  493.   is the only static part of the stack that any code should ever
  494.   refer to.
  495.  
  496. * COMMON is a type of memory area supported by FORTRAN.  Each
  497.   module's chunk of a COMMON segment starts at location 0, and
  498.   overlaps (usually duplicates) the pieces from all the other
  499.   modules.  The size of a COMMON segment is the size of the
  500.   largest chunk.
  501.  
  502. * MEMORY is an obsolete combination type.  All recent
  503.   implementations of LINK treat MEMORY as a synonym for PUBLIC.
  504.  
  505. * "AT number" defines a non-combinable segment at the absolute
  506.   memory location whose segment register value is "number".  This
  507.   form is useful for initializing data in fixed locations, such
  508.   as the 86 interrupt vector (IVECTOR SEGMENT AT 0 followed by
  509.   ORG 4 * INT_NUMBER), or for reading fixed memory locations,
  510.   such as the BIOS variables area (BIOS_DATA SEGMENT AT 040).
  511.  
  512. The combine type specification can be repeated in subsequent
  513. pieces of a given segment, but if it is, it must be the same in
  514. all pieces.
  515.  
  516. Finally, if no combine type is ever given for a named segment in
  517. a module, that segment is non-combinable-- no other modules may
  518. define that segment; the code given in the one module constitutes
  519. the entire segment.
  520.  
  521.  
  522. The "use" specification, recognized only by future versions of
  523. A386, tells whether the segment is a 32-bit segment.  The default
  524. value USE16 means the segment is a 16-bit segment: 32-bit
  525. registers, memory operands, and memory indexing will be encoded
  526. using address and operand override bytes.  The value USE32 or its
  527. synonym FLAT specify a 32-bit segment (to be loaded and run only
  528. in protected-mode environments such as Windows or OS/2).  In
  529. 32-bit segments, the 16-bit operands and addresses require the
  530. override opcode bytes, and the 32-bit operands and addresses
  531. don't.
  532.  
  533. At this writing, segments of type USE32 are not yet implemented.
  534. See the documentation files accompanying A386 on your registered
  535. A86+D86 disk, for the latest news on what is implemented in A386.
  536.                                                             10-11
  537.  
  538. The last specification available on a SEGMENT line is the class
  539. name, which is identified by being enclosed in single quotes.
  540. Unlike a segment name, which can be used as an instruction
  541. operand and hence cannot conflict with other assembler symbols, a
  542. class name can be assigned without regard to its usage elsewhere
  543. in the program.  It can even be a built-in A86 mnemonic.  In
  544. fact, both the SMALL and LARGE high-level-language models specify
  545. the class name 'CODE' for code segments, and the SMALL model
  546. specifies the class name 'DATA'.
  547.  
  548. If no class name is given for a segment, A86 specifies the null
  549. (zero length) string as the class name.
  550.  
  551.  
  552. DATA SEGMENT, STRUC and CODE SEGMENT Directives
  553.  
  554. The DATA SEGMENT and STRUC directives work in .OBJ mode exactly
  555. as they do in .COM mode-- they define a special assembly mode, in
  556. which declarations are made, but no object code is output.
  557. Offsets within DATA segments and structures are absolute, as in
  558. .COM mode.  Assembly resumes as before when an ENDS or CODE
  559. SEGMENT directive is encountered.
  560.  
  561. For MASM compatibility (especially in modules written to link to
  562. Turbo Pascal V4.0 programs), I now recognize the reserved symbols
  563. CODE, DATA, and STACK as ordinary relocatable segment names.  The
  564. ordinary functionality takes effect whenever a SEGMENT directive
  565. is given with CODE, DATA or STACK as the segment name, and with
  566. one or more relocatable parameters (e.g., PUBLIC) given after
  567. SEGMENT.
  568.  
  569.  
  570. The ENDS Directive
  571.  
  572. Syntax:  [seg_name] ENDS
  573.  
  574. The ENDS directive closes out the segment currently being
  575. assembled, and returns assembly to the segment being assembled
  576. before the last SEGMENT directive.  The "seg_name", if given,
  577. must match the name in that last SEGMENT directive.  ENDS allows
  578. you to "nest" segments inside one another.  For example, you can
  579. declare some static data variables that are specific to a certain
  580. section of code at the top of that section:
  581.  
  582.   _DATA SEGMENT BYTE PUBLIC 'DATA'
  583.       VAR1  DB ?
  584.       VAR2  DB ?
  585.   _DATA ENDS
  586.  
  587. These four lines can be inserted inside any other segment being
  588. assembled.  They will cause the two variable allocations to be
  589. tacked onto the segment _DATA; and assembly will then continue in
  590. whatever segment surrounded the four lines.  Observe that the
  591. "nesting" does not occur in the final program; only the
  592. presentation of the source code is nested.
  593.                                                             10-12
  594.  
  595. If you are not nesting segments inside one another, then the ENDS
  596. directive serves only to lend a clean, "block-structured"
  597. appearance to your source code.  It does not assist A86 in any
  598. particular way; in fact, it consumes a bit more object output
  599. memory (slightly reducing object output capacity) if you have
  600. ENDSs, rather than just starting up new segments with SEGMENT
  601. directives.
  602.  
  603.  
  604. Default Outer SEGMENT
  605.  
  606. Other assemblers outlaw any code outside of a SEGMENT
  607. declaration, forcing you to give a SEGMENT declaration before you
  608. can assemble anything.  A86 lets you assemble just your code; you
  609. don't have to worry about SEGMENTs if you don't want to.
  610.  
  611. If you do provide code outside of all SEGMENT declarations, A86
  612. performs the following steps, to find a reasonable place to put
  613. the code:
  614.  
  615. 1. If there are any segments explicitly declared whose name is or
  616.    ends with "_TEXT", then the first such segment declared is
  617.    used.  It is as if the SEGMENT declaration appeared at the top
  618.    of, rather than within, the program.
  619.  
  620. 2. If there is no such explicit segment, A86 creates a BYTE
  621.    PUBLIC segment of class 'CODE', and proceeds to construct a
  622.    name for the segment.  If there are no RETF instructions in
  623.    the outer segment, the name chosen is "_TEXT", conforming to
  624.    the SMALL model of computation.  If there is a RETF
  625.    instruction, the name chosen is "modulename_TEXT", where
  626.    "modulename" is the name of this module.  Recall that
  627.    "modulename" comes from the NAME directive if there is one;
  628.    from the name of the .OBJ file if there isn't.
  629.  
  630.  
  631. The GROUP Directive
  632.  
  633. Syntax:  group_name GROUP seg_name1, seg_name2, ...
  634.  
  635. The GROUP directive causes A86 to tell LINK that all the listed
  636. segments can fit into a single 64K-byte block of memory, and
  637. instruct LINK to make that fit.  (If they won't fit, LINK will
  638. issue an error message.)  Having declared the group, you can then
  639. use "group_name" as the segment register value that will allow
  640. simultaneous access to all the named segments.  The order of
  641. names given in the list does not necessarily determine the order
  642. in which the segments will finally appear within the group.
  643.  
  644. The most useful application of the GROUP directive is to allow
  645. you to structure the pieces of a program, all of whose code and
  646. data will fit into a single 64K segment.  You organize the pieces
  647. into SEGMENTs, and declare all the SEGMENTs to be within the same
  648. GROUP.  When the program starts, all segment registers are set to
  649. point to the GROUP, and you never have to worry about segment
  650. registers again in the program.
  651.                                                             10-13
  652.  
  653. WARNING: If your segments will be GROUPed in the final program,
  654. you should have the appropriate GROUP directive in every module
  655. assembled.  If you don't, then any memory pointers generated will
  656. be relative to the beginning of the individual named segments,
  657. not to the beginning of the whole group.
  658.  
  659. Because of the obscure scenario I described in the Overview
  660. section, Intel does not prohibit more than one GROUP from
  661. containing some of the same segments; so neither does A86.  Any
  662. pointers within a segment will be calculated from the beginning
  663. of the last GROUP within which the segment was declared.  But
  664. again, I have my doubts as to whether LINK will handle this
  665. correctly.
  666.  
  667.  
  668. The SEG Operator
  669.  
  670. Syntax:  SEG operand
  671.  
  672. The SEG operator returns the segment containing its operand-- a
  673. value suitable for loading into one of the segment registers. If
  674. the operand is an explicit far constant such as 01811:0100, the
  675. value returned is the lefthand component of the constant (01811
  676. in this example).  Otherwise, the result depends on A86's output
  677. mode:
  678.  
  679. When A86 is assembling to an OBJ file, the result is the named
  680. relocatable segment containing the operand.  SEG is most useful
  681. when the operand is not defined in this A86 module: in that case,
  682. the segment value will be plugged in by LINK.
  683.  
  684. When A86 is assembling to a COM file, SEG always returns the CS
  685. register, with one exception: symbols declared within a SEGMENT
  686. AT structure return the value of the containing segment.  COM
  687. files have no facility for explicitly specifying relocatable
  688. segments, so for compatibility A86 assumes that all non-absolute
  689. segment references are to the program's segment itself.
  690.  
  691.